package org.rulix.ogame.player.core;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.rulix.ogame.player.api.OgameCoreLogic;
import org.rulix.ogame.player.api.OgameFleetMovement;
import org.rulix.ogame.player.api.OgameLogicListener;
import org.rulix.ogame.player.api.OgameLoginStatus;
import org.rulix.ogame.player.core.httpworker.DelegatedCallable;
import org.rulix.ogame.player.core.httpworker.HttpEventListWorker;
import org.rulix.ogame.player.core.httpworker.HttpLoginWorker;

public class OgameCoreLogicImpl implements OgameCoreLogic {

	private OgameLoginStatus ogameLoginStatus = OgameLoginStatus.LOGGED_OUT;
	private OgameProfile ogameProfile;
	private HttpClient httpClient;
	private ExecutorService httpExecutor;
	private ScheduledExecutorService httpTimedExecutor;
	private List<OgameLogicListener> listeners;
	private List<OgameFleetMovement> fleetMovements;
	private OgameSession ogameSession = null;
	
	@Override
	public void destroy() {
		httpClient = null;
		httpExecutor.shutdownNow();
		httpTimedExecutor.shutdownNow();
		listeners.clear();
	}
	
	@Override
	public void init() {
		httpClient = new DefaultHttpClient();
		httpExecutor = Executors.newSingleThreadExecutor();
		httpTimedExecutor = Executors.newSingleThreadScheduledExecutor();
		listeners = Collections.synchronizedList(new ArrayList<OgameLogicListener>());
	}
	
	
	@Override
	public void logIn(String uni, String login, String password) throws OgameException {
		if ( ogameLoginStatus == OgameLoginStatus.LOGGED_OUT ) {
			changeStatusLoggingIn();
			HttpLoginWorker hlw = new HttpLoginWorker(this, uni, login, password);
			DelegatedCallable d = new DelegatedCallable(hlw);
			httpExecutor.submit(d);
		} else {
			throw new OgameException("Not logged out");
		}
	}

	@Override
	public void getPlanets() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void saveFleetFromPlanet() throws OgameException {
		
	}
	
	@Override
	public void getFleetMovements() throws OgameException {
		if ( ogameLoginStatus == OgameLoginStatus.LOGGED_IN ) {
			HttpEventListWorker helw = new HttpEventListWorker(this);
			DelegatedCallable d = new DelegatedCallable(helw);
			httpExecutor.submit(d);
		} else {
			throw new OgameException("Not logged in");
		}
	}
	
	
	
	@Override
	public void logOut() {
		// TODO Auto-generated method stub

	}

	@Override
	public void startBot() {
		// TODO Auto-generated method stub

	}

	@Override
	public void stopBot() {
		// TODO Auto-generated method stub

	}
	
	public HttpClient getHttpClient(){
		return this.httpClient;
	}

	@Override
	public void addOgameLogicListener(OgameLogicListener ogameLogicListener) {
		listeners.add(ogameLogicListener);
		
	}

	@Override
	public void removeOgameLogicListener(OgameLogicListener ogameLogicListener) {
		listeners.remove(ogameLogicListener);
	}
	
	//Login status changers;
	public void changeStatusLoggingIn(){
		ogameLoginStatus = OgameLoginStatus.LOGGING_IN;
		notifyListenersLogicLoginChangeStatus(ogameLoginStatus);
	}
	
	public void changeStatusLoggedIn(){
		ogameLoginStatus = OgameLoginStatus.LOGGED_IN;
		notifyListenersLogicLoginChangeStatus(ogameLoginStatus);
	}
	
	public void changeStatusLoggedOut(){
		ogameLoginStatus = OgameLoginStatus.LOGGED_OUT;
		notifyListenersLogicLoginChangeStatus(ogameLoginStatus);
	}
	
	//listeners notifications
	public void notifyListenersLogicLoginChangeStatus(OgameLoginStatus ogameLoginStatus){
		for (OgameLogicListener ogameLogicListener : listeners) {
			ogameLogicListener.loginChangeStatus(ogameLoginStatus);
		}
	}

	//listeners notifications
	public void notifyListenersFleetMovementsAvailable(){
		for (OgameLogicListener ogameLogicListener : listeners) {
			ogameLogicListener.fleetMovementsAvailable(fleetMovements);
		}
	}

	public void setOgameSession(OgameSession ogameSession) {
		this.ogameSession  = ogameSession;
	}
	
	public OgameSession getOgameSession() {
		return ogameSession;
	}
	
	public void setFleetMovements(List<OgameFleetMovement> fleetMovements) {
		this.fleetMovements = fleetMovements;
	}
}
